<!DOCTYPE html>
<html CN>







<head>
	
	
	<link rel="stylesheet" href="/css/allinone.min.css"> 

	
	<!-- Global Site Tag (gtag.js) - Google Analytics -->
	<script async src="https://www.googletagmanager.com/gtag/js?id=UA-42863699-1"></script>
	<script>
		window.dataLayer = window.dataLayer || [];
		function gtag(){dataLayer.push(arguments);}
		gtag('js', new Date());
		gtag('config', 'UA-42863699-1');
	</script>
	

	<meta charset="utf-8" />
	<meta http-equiv="X-UA-Compatible" content="IE=edge" />

	<title>aufs 简介以及在 docker 中的使用 | Cizixs Write Here</title>

	<meta name="HandheldFriendly" content="True" />
	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
	<meta name="generator" content="hexo">
	<meta name="author" content="Cizixs Wu">
	<meta name="description" content="">

	
	<meta name="keywords" content="">
	

	
	<link rel="shortcut icon" href="https://cizixs-blog.oss-cn-beijing.aliyuncs.com/006tNc79ly1g1qxfovpzyj30740743yg.jpg">
	

	
	<meta name="theme-color" content="#3c484e">
	<meta name="msapplication-TileColor" content="#3c484e">
	

	

	

	<meta property="og:site_name" content="Cizixs Write Here">
	<meta property="og:type" content="article">
	<meta property="og:title" content="aufs 简介以及在 docker 中的使用 | Cizixs Write Here">
	<meta property="og:description" content="">
	<meta property="og:url" content="http://cizixs.com/2017/09/13/docker-aufs-storage-driver/">

	
	<meta property="article:published_time" content="2017-09-13T00:09:00+08:00"/> 
	<meta property="article:author" content="Cizixs Wu">
	<meta property="article:published_first" content="Cizixs Write Here, /2017/09/13/docker-aufs-storage-driver/" />
	

	
	
	<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
	

	
	<script src="https://cdn.staticfile.org/highlight.js/9.10.0/highlight.min.js"></script>
	

	
	
<link rel="stylesheet" href="/css/prism-base16-ateliersulphurpool.light.css" type="text/css"></head>
<body class="post-template">
    <div class="site-wrapper">
        




<header class="site-header outer" style="z-index: 999">
    <div class="inner">
        
<nav class="site-nav"> 
    <div class="site-nav-left">
        <ul class="nav">
            <li>
                
                <a href="/" title="Home">Home</a>
                
            </li>
            
            
            <li>
                <a href="/about" title="About">About</a>
            </li>
            
            <li>
                <a href="/archives" title="Archives">Archives</a>
            </li>
            
            
        </ul> 
    </div>
    <div class="site-nav-right">
        
<div class="social-links" >
    
    <a class="social-link" title="weibo" href="https://weibo.com/1921727853" target="_blank" rel="noopener">
        <svg viewBox="0 0 1141 1024" xmlns="http://www.w3.org/2000/svg"><path d="M916.48 518.144q27.648 21.504 38.912 51.712t9.216 62.976-14.336 65.536-31.744 59.392q-34.816 48.128-78.848 81.92t-91.136 56.32-94.72 35.328-89.6 18.944-75.264 7.68-51.712 1.536-49.152-2.56-68.096-10.24-78.336-21.504-79.872-36.352-74.24-55.296-59.904-78.848q-16.384-29.696-22.016-63.488t-5.632-86.016q0-22.528 7.68-51.2t27.136-63.488 53.248-75.776 86.016-90.112q51.2-48.128 105.984-85.504t117.248-57.856q28.672-10.24 63.488-11.264t57.344 11.264q10.24 11.264 19.456 23.04t12.288 29.184q3.072 14.336 0.512 27.648t-5.632 26.624-5.12 25.6 2.048 22.528q17.408 2.048 33.792-1.536t31.744-9.216 31.232-11.776 33.28-9.216q27.648-5.12 54.784-4.608t49.152 7.68 36.352 22.016 17.408 38.4q2.048 14.336-2.048 26.624t-8.704 23.04-7.168 22.016 1.536 23.552q3.072 7.168 14.848 13.312t27.136 12.288 32.256 13.312 29.184 16.384zM658.432 836.608q26.624-16.384 53.76-45.056t44.032-64 18.944-75.776-20.48-81.408q-19.456-33.792-47.616-57.344t-62.976-37.376-74.24-19.968-80.384-6.144q-78.848 0-139.776 16.384t-105.472 43.008-72.192 60.416-38.912 68.608q-11.264 33.792-6.656 67.072t20.992 62.976 42.496 53.248 57.856 37.888q58.368 25.6 119.296 32.256t116.224 0.512 100.864-21.504 74.24-33.792zM524.288 513.024q20.48 8.192 38.912 18.432t32.768 27.648q10.24 12.288 17.92 30.72t10.752 39.424 1.536 42.496-9.728 38.912q-8.192 18.432-19.968 37.376t-28.672 35.328-40.448 29.184-57.344 18.944q-61.44 11.264-117.76-11.264t-88.064-74.752q-12.288-39.936-13.312-70.656t16.384-66.56q13.312-27.648 40.448-51.712t62.464-38.912 75.264-17.408 78.848 12.8zM361.472 764.928q37.888 3.072 57.856-18.432t21.504-48.128-15.36-47.616-52.736-16.896q-27.648 3.072-43.008 23.552t-17.408 43.52 9.728 42.496 39.424 21.504zM780.288 6.144q74.752 0 139.776 19.968t113.664 57.856 76.288 92.16 27.648 122.88q0 33.792-16.384 50.688t-35.328 17.408-35.328-14.336-16.384-45.568q0-40.96-22.528-77.824t-59.392-64.512-84.48-43.52-96.768-15.872q-31.744 0-47.104-15.36t-14.336-34.304 18.944-34.304 51.712-15.36zM780.288 169.984q95.232 0 144.384 48.64t49.152 146.944q0 30.72-10.24 43.52t-22.528 11.264-22.528-14.848-10.24-35.84q0-60.416-34.816-96.256t-93.184-35.84q-19.456 0-28.672-10.752t-9.216-23.04 9.728-23.04 28.16-10.752z" /></svg>
    </a>
    

    
    <a class="social-link" title="github" href="https://github.com/cizixs" target="_blank" rel="noopener">
        <svg viewBox="0 0 1049 1024" xmlns="http://www.w3.org/2000/svg"><path d="M524.979332 0C234.676191 0 0 234.676191 0 524.979332c0 232.068678 150.366597 428.501342 358.967656 498.035028 26.075132 5.215026 35.636014-11.299224 35.636014-25.205961 0-12.168395-0.869171-53.888607-0.869171-97.347161-146.020741 31.290159-176.441729-62.580318-176.441729-62.580318-23.467619-60.841976-58.234462-76.487055-58.234463-76.487055-47.804409-32.15933 3.476684-32.15933 3.476685-32.15933 53.019436 3.476684 80.83291 53.888607 80.83291 53.888607 46.935238 79.963739 122.553122 57.365291 152.97411 43.458554 4.345855-33.897672 18.252593-57.365291 33.028501-70.402857-116.468925-12.168395-239.022047-57.365291-239.022047-259.012982 0-57.365291 20.860106-104.300529 53.888607-140.805715-5.215026-13.037566-23.467619-66.926173 5.215027-139.067372 0 0 44.327725-13.906737 144.282399 53.888607 41.720212-11.299224 86.917108-17.383422 131.244833-17.383422s89.524621 6.084198 131.244833 17.383422C756.178839 203.386032 800.506564 217.29277 800.506564 217.29277c28.682646 72.1412 10.430053 126.029806 5.215026 139.067372 33.897672 36.505185 53.888607 83.440424 53.888607 140.805715 0 201.64769-122.553122 245.975415-239.891218 259.012982 19.121764 16.514251 35.636014 47.804409 35.636015 97.347161 0 70.402857-0.869171 126.898978-0.869172 144.282399 0 13.906737 9.560882 30.420988 35.636015 25.205961 208.601059-69.533686 358.967656-265.96635 358.967655-498.035028C1049.958663 234.676191 814.413301 0 524.979332 0z" /></svg>
    </a>
    

    
    <a class="social-link" title="stackoverflow" href="https://stackoverflow.com/users/1925083/cizixs" target="_blank" rel="noopener">
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M15 21h-10v-2h10v2zm6-11.665l-1.621-9.335-1.993.346 1.62 9.335 1.994-.346zm-5.964 6.937l-9.746-.975-.186 2.016 9.755.879.177-1.92zm.538-2.587l-9.276-2.608-.526 1.954 9.306 2.5.496-1.846zm1.204-2.413l-8.297-4.864-1.029 1.743 8.298 4.865 1.028-1.744zm1.866-1.467l-5.339-7.829-1.672 1.14 5.339 7.829 1.672-1.14zm-2.644 4.195v8h-12v-8h-2v10h16v-10h-2z"/></svg>
    </a>
    

    

    
    <a class="social-link" title="twitter" href="https://twitter.com/cizixs" target="_blank" rel="noopener">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M30.063 7.313c-.813 1.125-1.75 2.125-2.875 2.938v.75c0 1.563-.188 3.125-.688 4.625a15.088 15.088 0 0 1-2.063 4.438c-.875 1.438-2 2.688-3.25 3.813a15.015 15.015 0 0 1-4.625 2.563c-1.813.688-3.75 1-5.75 1-3.25 0-6.188-.875-8.875-2.625.438.063.875.125 1.375.125 2.688 0 5.063-.875 7.188-2.5-1.25 0-2.375-.375-3.375-1.125s-1.688-1.688-2.063-2.875c.438.063.813.125 1.125.125.5 0 1-.063 1.5-.25-1.313-.25-2.438-.938-3.313-1.938a5.673 5.673 0 0 1-1.313-3.688v-.063c.813.438 1.688.688 2.625.688a5.228 5.228 0 0 1-1.875-2c-.5-.875-.688-1.813-.688-2.75 0-1.063.25-2.063.75-2.938 1.438 1.75 3.188 3.188 5.25 4.25s4.313 1.688 6.688 1.813a5.579 5.579 0 0 1 1.5-5.438c1.125-1.125 2.5-1.688 4.125-1.688s3.063.625 4.188 1.813a11.48 11.48 0 0 0 3.688-1.375c-.438 1.375-1.313 2.438-2.563 3.188 1.125-.125 2.188-.438 3.313-.875z"/></svg>

    </a>
    

    
    <a class="social-link" title="instagram" href="https://www.instagram.com/cizixs/" target="_blank" rel="noopener">
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z"/></svg>
    </a>
    
    
    
</div>
    </div>
</nav>
    </div>
</header>


<main id="site-main" class="site-main outer" role="main">
    <div class="inner">
        <header class="post-full-header">
            <section class="post-full-meta">
                <time  class="post-full-meta-date" datetime="2017-09-12T16:00:00.000Z" itemprop="datePublished">
                    2017-09-13
                </time>
                
                <span class="date-divider">/</span>
                
                <a href="/categories/blog/">blog</a>&nbsp;&nbsp;
                
                
            </section>
            <h1 class="post-full-title">aufs 简介以及在 docker 中的使用</h1>
        </header>
        <article class="post-full no-image">
            
            <section class="post-full-content">
                <div id="lightgallery" class="markdown-body">
                    <h2 id="AUFS-简介"><a href="#AUFS-简介" class="headerlink" title="AUFS 简介"></a>AUFS 简介</h2><p>AUFS 的全称是 Advanced Multi-layered unification filesytem，它的主要功能是：把多个目录结合成一个目录，对外使用。</p>
<p>把多个目录 mount 成一个，那么读写操作是怎样的呢？</p>
<ul>
<li>默认情况下，最上层的目录为读写层，只能有一个；下面可以有一个或者多个只读层</li>
<li>读文件，打开文件的时候使用了 <code>O_RDONLY</code> 选项：从最上面一个开始往下逐层去找，打开第一个找到的文件，读取其中的内容</li>
<li>写文件，打开文件时用了 <code>O_WRONLY</code> 或者 <code>O_RDWR</code> 选项<ul>
<li>如果在最上层找到了该文件，直接打开</li>
<li>否则，从上往下开始查找，找到文件后，把文件复制到最上层，然后再打开这个 copy（所以，如果要读写的文件很大，这个过程耗时会很久）</li>
</ul>
</li>
<li>删除文件：在最上层创建一个 whiteout 文件，<code>.wh.&lt;origin_file_name&gt;</code>，就是在原来的文件名字前面加上 <code>.wh.</code> </li>
</ul>
<h2 id="aufs-简单实验"><a href="#aufs-简单实验" class="headerlink" title="aufs 简单实验"></a>aufs 简单实验</h2><p>Ubuntu 系统默认已经安装了 aufs，对应的安装包是 <code>aufs-tools</code>。下面我们就做一个简单的试验，看看 aufs 具体的样子。</p>
<p>工作目录可以随便选择，后面的操作都是在这个目录进行的。首先创建三个子目录: </p>
<ul>
<li><code>base</code> 作为底层的目录</li>
<li><code>top</code> 作为上层的目录</li>
<li><code>mnt</code>： aufs 使用的挂载点，会把上面两个目录挂载到这里</li>
</ul>
<p>然后创建几个文件，如下：</p>
<pre><code>➜  tree                     
.
├── base
│   ├── common.txt
│   └── hello.txt
├── mnt
└── top
    ├── common.txt
    └── foo.txt
</code></pre><p>接下来使用 aufs，把 <code>base</code> 和 <code>top</code> 一起 mount 到 <code>./mnt</code> 目录：</p>
<pre><code>➜  sudo mount -t aufs -o br=./top:./base none ./mnt
</code></pre><p>在 aufs 中，<code>base/</code> 和 <code>top/</code> 被称为 branch，它们就是源目录。</p>
<p>这个 mount 命令的参数意义是这样的：</p>
<ul>
<li><code>-t aufs</code>：mount 的文件类型，使用的是 aufs</li>
<li><code>-o</code>：传递个 aufs 的选项，每个文件类型的选项不同</li>
<li><code>br</code>：表示 branch，也就是 aufs 需要的的各个目录</li>
<li><code>none</code>：这个本来是设备的名字，但是我们并没有用到任何设备，只会用到文件夹，因此这里为 none</li>
<li><code>./mnt</code>：挂载点，也就是内容最终出现的目录</li>
</ul>
<p>默认情况下，<code>-o</code> 后面的第一个目录是以可读写模式挂载的，剩下的目录都是只读模式（和 docker 容器模型非常一致）。</p>
<p>查看挂载好之后的组织形式，发现 <code>./mnt</code> 中出现了原来两个文件夹的综合内容，其中 <code>common.txt</code> 文件选择的是 <code>top/</code> 文件夹的。</p>
<pre><code>➜  tree
.
├── base
│   ├── common.txt
│   └── hello.txt
├── mnt
│   ├── common.txt
│   ├── foo.txt
│   └── hello.txt
└── top
    ├── common.txt
    └── foo.txt

➜  cat mnt/common.txt 
top
</code></pre><p>如果要修改 <code>common.txt</code> 文件，会发现只有 <code>top</code> 目录对应的内容发生了变化，<code>base</code> 下面的内容会保持不动：</p>
<pre><code>➜  echo changed &gt; ./mnt/common.txt
➜  cat top/common.txt 
changed
➜  cat base/common.txt 
base
</code></pre><p>这是因为 aufs 会逐层去查找文件，发现最上层存在文件 <code>common.txt</code> 并且是可写的，就会直接操作这个文件。类似的，如果是修改 <code>foo.txt</code> 也会直接反应在 <code>top/</code> 目录里面。</p>
<p>但是如果我们想要修改 <code>hello.txt</code> 文件，和预期不一样的是，<code>base/hello.txt</code> 并没有变化，而是新建了一个 <code>top/hello.txt</code> 文件，所有的操作都是在这个文件进行的。实验结果如下：</p>
<pre><code>➜  echo hello, world &gt; mnt/hello.txt 
➜  tree
.
├── base
│   ├── common.txt
│   └── hello.txt
├── mnt
│   ├── common.txt
│   ├── foo.txt
│   └── hello.txt
└── top
    ├── common.txt
    ├── foo.txt
    └── hello.txt
</code></pre><p>这是因为，aufs 从上往下查找文件，虽然在 <code>base/</code> 中发现了 <code>hello.txt</code> 文件，但是这个 branch 是以只读的方式挂载的，所以 aufs 并不能直接修改它，而是把它拷贝一份到上层，并对这个拷贝进行修改。</p>
<p>当然我们可以在 mount 的指定每个 branch 的读写模式，比如把两个 branch 都以可写的方式挂载：</p>
<pre><code>➜  sudo mount -t aufs -o br=./top=rw:./base=rw none ./mnt
</code></pre><p>那么修改文件的规则会发生一些变化，文件查找还是从前到后，但是一旦发现文件，就能直接修改这个 branch 的文件内容，而不需要进行拷贝了。具体的实验就不做了，操作也非常简单，读者可以自行完成。</p>
<p>可以指定的权限一共有三种：</p>
<ul>
<li><code>rw</code>：可读可写，用户能直接修改这个 branch 的文件内容</li>
<li><code>ro</code>：只读，用户不能通过 aufs 的接口对文件进行写操作，只能读取里面的内容</li>
<li><code>rr</code>：real read only，底层的文件本来就是只读的（这种情况比较少见），这种情况下，aufs 就不用担心文件不通过它的接口被修改的情况</li>
</ul>
<p>除了读写模式之外，还有一个重要的属性——<code>whiteout</code>。</p>
<p>通过 aufs 指定的读写模式，只有用户通过最终的挂载点访问才有效，如果用户绕过挂载点，直接修改原来的文件，aufs 应该怎么处理呢？这个行为是由一个参数控制的，<code>udba</code>（全称是 User Direct Branch Access），这个参数有三个可选值：</p>
<ul>
<li><code>udba=none</code>：aufs 不会进行任何数据同步的检查，因此性能会高一点，但是可能会出现数据不一致的情况。如果用户能保证文件不会直接被修改，或者对文件内容一致性要求不高，可以使用</li>
<li><code>udba=reval</code>：aufs 会检查底层的文件有没有改动，如果有的话，把改动的内容更新到挂载点。这个性能会导致 aufs 产生额外的性能损耗</li>
<li><code>udba=notify</code>：通过 inotify 监听底层的文件变化，基于事件驱动，能够减少第二种方式的性能损耗</li>
</ul>
<p>说了这么多，可以看出来其实 aufs 最核心的功能还是那句话：<strong>把多个目录合并成一个目录，让用户决定在操作统一的文件系统</strong>。虽然看起来很有趣，那么 aufs 有哪些实际的用处呢？当然它被我们提起是因为 docker 可以用它来保存镜像和容器，但是 aufs 出现的时间要比 docker 长很多，它常见的用法包括：</p>
<ul>
<li>Linux 光盘演示和教程，录制了 Linux 的光盘可以用来让用户体验，但是光盘的内容是只读的，可以通过 aufs 把光盘和 U 盘或者磁盘 mount 到一起，用户对文件的修改保存到后面的存储上</li>
<li>如果系统上因为各种原因，不同用户的 home 目录保存在不同的路径和磁盘上，可以通过 aufs 把它们 mount 到一起，统一进行操作</li>
</ul>
<p>当然，下面我们就要讲讲 aufs 在 docker 中的用法。</p>
<h2 id="docker-使用-aufs-作为-storage-driver"><a href="#docker-使用-aufs-作为-storage-driver" class="headerlink" title="docker 使用 aufs 作为 storage driver"></a>docker 使用 aufs 作为 storage driver</h2><p>在 ubuntu 系统中，安装了 docker 之后，docker 运行默认选择的 storage driver 就是 aufs，通过 <code>docker info</code> 命令可以查看，我自己的机器上显示的信息如下：</p>
<pre><code>➜  docker info
Server Version: 17.03.0-ce
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 228
 Dirperm1 Supported: true
</code></pre><p>所有 aufs 的内容都在 <code>/var/lib/docker/aufs</code> 目录中，这个目录下面有三个子目录：</p>
<pre><code>➜ tree -L 1 /var/lib/docker/aufs
/var/lib/docker/aufs
├── diff
├── layers
└── mnt
</code></pre><ul>
<li><code>diff</code>：镜像每一层的内容，每个文件夹代表一个层</li>
<li><code>layers</code>：镜像各层是怎么组织的 metadata，每个文件代表一个层，这个文件中保存着它下面所有层的 ID（按照顺序）</li>
<li><code>mnt</code>: 镜像或者容器的 mountpoints，也就是容器最终看到的文件系统的样子</li>
</ul>
<p>通过这三个子目录，docker 就能实现镜像的分层存储、容器的 Copy-On-Write 启动。</p>
<h2 id="docker-容器的文件存储解析"><a href="#docker-容器的文件存储解析" class="headerlink" title="docker 容器的文件存储解析"></a>docker 容器的文件存储解析</h2><p>先来看看镜像，docker 的镜像是分层的，而且这些层之间有父子关系，它们共同组成了我们看到的一个个镜像。在本地，这些层是保存在 <code>/var/lib/docker/aufs/diff</code> 目录下的，我们可以用 <code>docker inspect ubuntu:16.04</code> 查看 <code>ubuntu:16.04</code> 有哪些层：</p>
<pre><code>&quot;RootFS&quot;: {
            &quot;Type&quot;: &quot;layers&quot;,
            &quot;Layers&quot;: [
                &quot;sha256:90edd0ba21c8da7e530c3fdb0af496a07a33c285c7e51f30de80c50c624a5905&quot;,
                &quot;sha256:267964ef478ec7e5969fc9c6efa41026195bc9bc4c6d6a06aa319adbd4378b5c&quot;,
                &quot;sha256:bec30309c6f4462637b06947692a17fd3e3ba6a0233f74c7c9292b4930421541&quot;,
                &quot;sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef&quot;,
                &quot;sha256:4a3596d391da67de46a4f50b07f69277e4c81d65debdf68b99aa726959602e39&quot;,
                &quot;sha256:72a672688aec3c93f4a1c6af75494c163347ad5319a582fe01c435bc84b08295&quot;,
                &quot;sha256:11d4787bae4222ff2790dc6d9678d8c205286b86c33cad3ec80762602799384c&quot;,
                &quot;sha256:0e593a4c1af6701dd33b58fead3fdb276cd2b87f020085297e8f690316e61b85&quot;,
                &quot;sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef&quot;,
                &quot;sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef&quot;
            ]
        }
</code></pre><p>可以看到，<code>ubuntu:16.04</code> 一共有 10 层，每一层都对应了 <code>aufs/diff</code> 下面的一个目录，但是每个目录名和上面的 <code>sha256</code> ID 并不相同。</p>
<p>接下来，我们运行容器：</p>
<pre><code>$ docker run -d ubuntu:16.04 sh -c &quot;while true; do sleep 1; echo 1; done&quot;
</code></pre><p>这个容器会在 <code>aufs/mnt</code> 目录下创建一个目录：<code>/var/lib/docker/aufs/mnt/223993596e6e22217d86604b374e24d973ebe48254f34a92a5e960d4e3860caa</code>，这也是容器中最终看到的文件系统的内容。</p>
<p>怎么中找到每个容器的层级关系呢？可以先通过通过 <code>cat /proc/mounts</code> 看到 aufs 的内部 ID(si)，比如下面的 <code>bca8de84a45d534b</code>：</p>
<pre><code>➜  cat /proc/mounts| grep aufs
none /var/lib/docker/aufs/mnt/223993596e6e22217d86604b374e24d973ebe48254f34a92a5e960d4e3860caa aufs rw,relatime,si=bca8de84a45d534b,dio,dirperm1 0 0
</code></pre><p>然后就能根据这个 id，查看它保存的各个 branch 的信息（对应了 docker 的每个层）：</p>
<pre><code>➜  cat /sys/fs/aufs/si_bca8de84a45d534b/br[0-9]*
/var/lib/docker/aufs/diff/223993596e6e22217d86604b374e24d973ebe48254f34a92a5e960d4e3860caa=rw
/var/lib/docker/aufs/diff/223993596e6e22217d86604b374e24d973ebe48254f34a92a5e960d4e3860caa-init=ro+wh
/var/lib/docker/aufs/diff/0809f5e8e6753bce10504289fceed0c377c6cc99e2a8d66505c56f01b85217a3=ro+wh
/var/lib/docker/aufs/diff/5febf4aecb9a60edb6d789da279490e3677f40b2e5af3bdfeec51bd2d1bef230=ro+wh
/var/lib/docker/aufs/diff/ec53b179c0bf8a9f9d729e19ca9ecbc7230d4c5daa7bf88bc2ef049a6c939800=ro+wh
/var/lib/docker/aufs/diff/2d1b95d7488f268999bfe058ca114c2efdbc0772f57ee7f6c96bbeb05577f2db=ro+wh
/var/lib/docker/aufs/diff/55d5a8091dc476bf0f4e39a119408acb4b8b690e3ace7022e7aaeea30b404d20=ro+wh
/var/lib/docker/aufs/diff/893023d4e2be28ba1660dd035bd0b3892478c50c83d2c8d6477fa9170068d2e4=ro+wh
/var/lib/docker/aufs/diff/f876a0ffdfa44a939b8b851f6b2cce086836acff6d55701739b2ad8d786ae346=ro+wh
/var/lib/docker/aufs/diff/e1863e30cbc5198d0c84f6611c0f5b2a6750abcefdb29aa57c4c4cd0becadd54=ro+wh
/var/lib/docker/aufs/diff/dcc613560b91ab550919a7f5b89025b1144ee63fa6dcdab929dec237ef3e8280=ro+wh
/var/lib/docker/aufs/diff/b671e25db34edc80d115c50338c9546faad8abf704c1d5c1450a9d9a7d84e8b6=ro+wh
</code></pre><p>可以看到，除了第一个是 <code>rw</code> 之外，其他都是 <code>ro+wh</code>（<code>ro</code> 表示 readonly 只读，<code>wh</code> 表示 whiteout，目录中可以包含 whiteout 文件），你可以查看各个目录的内容，它们对应了每个层的修改。</p>
<p><img src="https://docs.docker.com/engine/userguide/storagedriver/images/aufs_layers.jpg" alt=""></p>
<p>最终看到的文件是这样的：</p>
<pre><code>$ ls aufs/mnt/223993596e6e22217d86604b374e24d973ebe48254f34a92a5e960d4e3860caa     
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
</code></pre><p>因为我运行的容器并没有修改任何文件，因此最上面的层最开始为空。在容器中创建一个 <code>/root/hello.txt</code> 文件，这个目录就能看到新创建的文件：</p>
<pre><code>➜  ls aufs/diff/223993596e6e22217d86604b374e24d973ebe48254f34a92a5e960d4e3860caa
➜  tree aufs/diff/223993596e6e22217d86604b374e24d973ebe48254f34a92a5e960d4e3860caa/
aufs/diff/223993596e6e22217d86604b374e24d973ebe48254f34a92a5e960d4e3860caa/
└── root
    └── hello.txt

1 directory, 1 file
</code></pre><p>同理，直接在这个目录中新建文件也能在容器里看到。</p>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>aufs 是 docker 最早选择的存储驱动，因为 docker 公司最开始支持的操作系统为 Debian。aufs 概念很简单，非常容易理解和使用，但是 aufs 也有它的问题。</p>
<p>最大的问题是它不没有进入到 Linux 内核，因此不能保证可移植性，虽然像 ubuntu 这种发行版默认支持 aufs，但并不是所有系统都如此，比如 centos 就默认没有提供 aufs 支持。之所以没有合并到内核，据说是因为 aufs 的实现代码很冗杂，Linus 认为代码质量太差，虽然开发者多次精简，最终还是没有进入到内核，而且在短时间内也不会有什么变化。</p>
<p>另外的问题是 aufs 对性能有比较大的影响，通过上面的知识，我们至少能看到两个性能问题：第一次修改一个大文件会非常耗时；另外层级过多也会影响整体的读写性能。此外，<a href="https://sthbrx.github.io/blog/2015/10/30/docker-just-stop-using-aufs/" target="_blank" rel="noopener">这里有篇文章</a>提出，aufs 在频繁打开文件的时候性能损耗很大，虽然只是一个例子，而且没有给出 root cause，但能从另外一个侧面反应出 aufs 性能确实有待商榷。</p>
<p>如果在生产环境适用，上面两点因素会使很多人不会选择 aufs。但是 aufs 非常适合在开发环境，或者对性能要求较低的情况，因为 ubuntu 默认的驱动就是 aufs，而且它确实足够简单，维护的压力会小很多。</p>
<h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><ul>
<li><a href="https://coolshell.cn/articles/17061.html" target="_blank" rel="noopener">DOCKER基础技术：AUFS</a></li>
</ul>

                </div>
            </section>
        </article>
    </div>
    
<nav class="pagination">
    
    
    <a class="prev-post" title="vxlan 协议原理简介" href="/2017/09/25/vxlan-protocol-introduction/">
        ← vxlan 协议原理简介
    </a>
    
    <span class="prev-next-post">•</span>
    
    <a class="next-post" title="使用 pprof 和火焰图调试 golang 应用" href="/2017/09/11/profiling-golang-program/">
        使用 pprof 和火焰图调试 golang 应用 →
    </a>
    
    
</nav>

    <div class="inner">
    <!-- Begin Mailchimp Signup Form -->
    <link href="//cdn-images.mailchimp.com/embedcode/classic-10_7.css" rel="stylesheet" type="text/css">
    <style type="text/css">
    	#mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; }
    	/* Add your own Mailchimp form style overrides in your site stylesheet or in this style block.
    	   We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */
    </style>
    <div id="mc_embed_signup">
    <form action="https://cizixs.us7.list-manage.com/subscribe/post?u=2d561b8dea52d73a2e05e6dcb&amp;id=5c710f135b" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
        <div id="mc_embed_signup_scroll">
    	<h2>订阅本博客，第一时间收到文章更新</h2>
    <div class="indicates-required"><span class="asterisk">*</span> indicates required</div>
    <div class="mc-field-group">
    	<label for="mce-EMAIL">邮件地址  <span class="asterisk">*</span>
    </label>
    	<input type="email" value="" name="EMAIL" class="required email" id="mce-EMAIL">
    </div>
    	<div id="mce-responses" class="clear">
    		<div class="response" id="mce-error-response" style="display:none"></div>
    		<div class="response" id="mce-success-response" style="display:none"></div>
    	</div>    <!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups-->
        <div style="position: absolute; left: -5000px;" aria-hidden="true"><input type="text" name="b_2d561b8dea52d73a2e05e6dcb_5c710f135b" tabindex="-1" value=""></div>
        <div class="clear"><input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
        </div>
    </form>
    </div>
    <script type='text/javascript' src='//s3.amazonaws.com/downloads.mailchimp.com/js/mc-validate.js'></script><script type='text/javascript'>(function($) {window.fnames = new Array(); window.ftypes = new Array();fnames[0]='EMAIL';ftypes[0]='email';}(jQuery));var $mcj = jQuery.noConflict(true);</script>
    <!--End mc_embed_signup-->
    </div>

    <div class="inner">
        <div id="disqus_thread"></div>
    </div>

    
</main>

<div class="t-g-control">
    <div class="gotop">
        <svg class="icon" width="32px" height="32px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M793.024 710.272a32 32 0 1 0 45.952-44.544l-310.304-320a32 32 0 0 0-46.4 0.48l-297.696 320a32 32 0 0 0 46.848 43.584l274.752-295.328 286.848 295.808z" fill="#8a8a8a" /></svg>
    </div>
    <div class="toc-control">
        <svg class="icon toc-icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M779.776 480h-387.2a32 32 0 0 0 0 64h387.2a32 32 0 0 0 0-64M779.776 672h-387.2a32 32 0 0 0 0 64h387.2a32 32 0 0 0 0-64M256 288a32 32 0 1 0 0 64 32 32 0 0 0 0-64M392.576 352h387.2a32 32 0 0 0 0-64h-387.2a32 32 0 0 0 0 64M256 480a32 32 0 1 0 0 64 32 32 0 0 0 0-64M256 672a32 32 0 1 0 0 64 32 32 0 0 0 0-64" fill="#8a8a8a" /></svg>
        <svg class="icon toc-close" style="display: none;" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 960c-247.039484 0-448-200.960516-448-448S264.960516 64 512 64 960 264.960516 960 512 759.039484 960 512 960zM512 128.287273c-211.584464 0-383.712727 172.128262-383.712727 383.712727 0 211.551781 172.128262 383.712727 383.712727 383.712727 211.551781 0 383.712727-172.159226 383.712727-383.712727C895.712727 300.415536 723.551781 128.287273 512 128.287273z" fill="#8a8a8a" /><path d="M557.05545 513.376159l138.367639-136.864185c12.576374-12.416396 12.672705-32.671738 0.25631-45.248112s-32.704421-12.672705-45.248112-0.25631l-138.560301 137.024163-136.447897-136.864185c-12.512727-12.512727-32.735385-12.576374-45.248112-0.063647-12.512727 12.480043-12.54369 32.735385-0.063647 45.248112l136.255235 136.671523-137.376804 135.904314c-12.576374 12.447359-12.672705 32.671738-0.25631 45.248112 6.271845 6.335493 14.496116 9.504099 22.751351 9.504099 8.12794 0 16.25588-3.103239 22.496761-9.247789l137.567746-136.064292 138.687596 139.136568c6.240882 6.271845 14.432469 9.407768 22.65674 9.407768 8.191587 0 16.352211-3.135923 22.591372-9.34412 12.512727-12.480043 12.54369-32.704421 0.063647-45.248112L557.05545 513.376159z" fill="#8a8a8a" /></svg>
    </div>
    <div class="gobottom">
        <svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M231.424 346.208a32 32 0 0 0-46.848 43.584l297.696 320a32 32 0 0 0 46.4 0.48l310.304-320a32 32 0 1 0-45.952-44.544l-286.848 295.808-274.752-295.36z" fill="#8a8a8a" /></svg>
    </div>
</div>
<div class="toc-main" style="right: -100%">
    <div class="post-toc">
        <span>TOC</span>
        <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#AUFS-简介"><span class="toc-text">AUFS 简介</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#aufs-简单实验"><span class="toc-text">aufs 简单实验</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#docker-使用-aufs-作为-storage-driver"><span class="toc-text">docker 使用 aufs 作为 storage driver</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#docker-容器的文件存储解析"><span class="toc-text">docker 容器的文件存储解析</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#总结"><span class="toc-text">总结</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#参考资料"><span class="toc-text">参考资料</span></a></li></ol>
    </div>
</div>



        

<aside class="read-next outer">
    <div class="inner">
        <div class="read-next-feed">
            
            

<article class="read-next-card"  style="background-image: url(https://cizixs-blog.oss-cn-beijing.aliyuncs.com/006tNc79ly1g1qxcn9ft3j318w0txdo6.jpg)"  >
  <header class="read-next-card-header">
    <small class="read-next-card-header-sitetitle">&mdash; Cizixs Write Here &mdash;</small>
    <h3 class="read-next-card-header-title">Recent Posts</h3>
  </header>
  <div class="read-next-divider">
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
      <path d="M13 14.5s2 3 5 3 5.5-2.463 5.5-5.5S21 6.5 18 6.5c-5 0-7 11-12 11C2.962 17.5.5 15.037.5 12S3 6.5 6 6.5s4.5 3.5 4.5 3.5"/>
    </svg>
  </div>
  <div class="read-next-card-content">
    <ul>
      
      
      
      <li>
        <a href="/2018/08/26/what-is-istio/">什么是 istio</a>
      </li>
      
      
      
      <li>
        <a href="/2018/08/25/knative-serverless-platform/">serverless 平台 knative 简介</a>
      </li>
      
      
      
      <li>
        <a href="/2018/06/25/kubernetes-resource-management/">kubernetes 资源管理概述</a>
      </li>
      
      
      
      <li>
        <a href="/2018/01/24/use-prometheus-and-grafana-to-monitor-linux-machine/">使用 promethues 和 grafana 监控自己的 linux 机器</a>
      </li>
      
      
      
      <li>
        <a href="/2018/01/13/linux-udp-packet-drop-debug/">linux 系统 UDP 丢包问题分析思路</a>
      </li>
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    </ul>
  </div>
  <footer class="read-next-card-footer">
    <a href="/archives">  MORE  → </a>
  </footer>
</article>


            
            
            
        </div>
    </div>
</aside>


<footer class="site-footer outer">

	<div class="site-footer-content inner">
		<section class="copyright">
			<a href="/" title="Cizixs Write Here">Cizixs Write Here</a>
			&copy; 2019
		</section>
		<nav class="site-footer-nav">
			
            <a href="https://hexo.io" title="Hexo" target="_blank" rel="noopener">Hexo</a>
            <a href="https://github.com/xzhih/hexo-theme-casper" title="Casper" target="_blank" rel="noopener">Casper</a>
        </nav>
    </div>
</footer>






<div class="floating-header" >
	<div class="floating-header-logo">
        <a href="/" title="Cizixs Write Here">
			
                <img src="https://cizixs-blog.oss-cn-beijing.aliyuncs.com/006tNc79ly1g1qxfovpzyj30740743yg.jpg" alt="Cizixs Write Here icon" />
			
            <span>Cizixs Write Here</span>
        </a>
    </div>
    <span class="floating-header-divider">&mdash;</span>
    <div class="floating-header-title">aufs 简介以及在 docker 中的使用</div>
    <progress class="progress" value="0">
        <div class="progress-container">
            <span class="progress-bar"></span>
        </div>
    </progress>
</div>
<script>
   $(document).ready(function () {
    var progressBar = document.querySelector('progress');
    var header = document.querySelector('.floating-header');
    var title = document.querySelector('.post-full-title');
    var lastScrollY = window.scrollY;
    var lastWindowHeight = window.innerHeight;
    var lastDocumentHeight = $(document).height();
    var ticking = false;

    function onScroll() {
        lastScrollY = window.scrollY;
        requestTick();
    }
    function requestTick() {
        if (!ticking) {
            requestAnimationFrame(update);
        }
        ticking = true;
    }
    function update() {
        var rect = title.getBoundingClientRect();
        var trigger = rect.top + window.scrollY;
        var triggerOffset = title.offsetHeight + 35;
        var progressMax = lastDocumentHeight - lastWindowHeight;
            // show/hide floating header
            if (lastScrollY >= trigger + triggerOffset) {
                header.classList.add('floating-active');
            } else {
                header.classList.remove('floating-active');
            }
            progressBar.setAttribute('max', progressMax);
            progressBar.setAttribute('value', lastScrollY);
            ticking = false;
        }

        window.addEventListener('scroll', onScroll, {passive: true});
        update();

        // TOC
        var width = $('.toc-main').width();
        $('.toc-control').click(function () {
            if ($('.t-g-control').css('width')=="50px") {
                if ($('.t-g-control').css('right')=="0px") {
                    $('.t-g-control').animate({right: width}, "slow");
                    $('.toc-main').animate({right: 0}, "slow");
                    toc_icon()
                } else {
                    $('.t-g-control').animate({right: 0}, "slow");
                    $('.toc-main').animate({right: -width}, "slow");
                    toc_icon()
                }
            } else {
                if ($('.toc-main').css('right')=="0px") {
                    $('.toc-main').slideToggle("fast", toc_icon());
                } else {
                    $('.toc-main').css('right', '0px');
                    toc_icon()
                }
            }
        })

        function toc_icon() {
            if ($('.toc-icon').css('display')=="none") {
                $('.toc-close').hide();
                $('.toc-icon').show();
            } else {
                $('.toc-icon').hide();
                $('.toc-close').show();
            }
        }

        $('.gotop').click(function(){
            $('html,body').animate({scrollTop:$('.post-full-header').offset().top}, 800);
        });
        $('.gobottom').click(function () {
            $('html,body').animate({scrollTop:$('.pagination').offset().top}, 800);
        });

        // highlight
        // https://highlightjs.org
        $('pre code').each(function(i, block) {
            hljs.highlightBlock(block);
        });
        $('td.code').each(function(i, block) {
            hljs.highlightBlock(block);
        });

        console.log("this theme is from https://github.com/xzhih/hexo-theme-casper")
    });
</script>



<link rel="stylesheet" href="https://cdn.staticfile.org/lightgallery/1.3.9/css/lightgallery.min.css">



<script src="https://cdn.staticfile.org/lightgallery/1.3.9/js/lightgallery.min.js"></script>


<script>
	$(function () {
		var postImg = $('#lightgallery').find('img');
		postImg.addClass('post-img');
		postImg.each(function () {
			var imgSrc = $(this).attr('src');
			$(this).attr('data-src', imgSrc);
		});
		$('#lightgallery').lightGallery({selector: '.post-img'});
	});
</script>



<script>

/**
*  RECOMMENDED CONFIGURATION VARIABLES: EDIT AND UNCOMMENT THE SECTION BELOW TO INSERT DYNAMIC VALUES FROM YOUR PLATFORM OR CMS.
*  LEARN WHY DEFINING THESE VARIABLES IS IMPORTANT: https://disqus.com/admin/universalcode/#configuration-variables*/

var disqus_config = function () {
this.page.url = 'http://cizixs.com/2017/09/13/docker-aufs-storage-driver/';  // Replace PAGE_URL with your page's canonical URL variable
this.page.identifier = 'http://cizixs.com/2017/09/13/docker-aufs-storage-driver/'; // Replace PAGE_IDENTIFIER with your page's unique identifier variable
};

(function() { // DON'T EDIT BELOW THIS LINE
var d = document, s = d.createElement('script');
s.src = 'https://cizixs.disqus.com/embed.js';
s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
})();
</script>
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
                            


    </div>
</body>
</html>
